package pe.gob.osce.sirenas.dao.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import pe.gob.osce.sirenas.dao.PersonaDAOLocal;
import pe.gob.osce.sirenas.dao.convert.DomicilioConvert;
import pe.gob.osce.sirenas.dao.convert.FichaArbitralConvert;
import pe.gob.osce.sirenas.dao.convert.PersonaConvert;
import pe.gob.osce.sirenas.model.BusquedaFichaDTO;
import pe.gob.osce.sirenas.model.DomicilioDTO;
import pe.gob.osce.sirenas.model.PersonaDTO;
import pe.gob.osce.sirenas.model.jpa.Domicilio;
import pe.gob.osce.sirenas.model.jpa.FichaArbitral;
import pe.gob.osce.sirenas.model.jpa.Persona;
import pe.gob.osce.sirenas.model.jpa.rectificaciones.HistorialPersona;
import pe.gob.osce.sirenas.util.ConstanteEJB;
import pe.gob.osce.sirenas.util.ModeloException;

@Stateless
public class PersonaDAOImpl implements PersonaDAOLocal {

	@PersistenceContext(unitName = "pe.gob.osce.sirenas.be.pu")
	private EntityManager em;
	

	ResourceBundle propSirenas = ResourceBundle.getBundle(ConstanteEJB.PROPERTIES);
	
	@Override
	public Persona insertar(Persona persona) throws Exception {
		try{
			em.merge(persona);
			em.flush();
		} catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_INSERT), e);
		}
		return persona;
	}

	@Override
	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
	public Persona actualizar(Persona persona) throws Exception{
		try {
			StringBuilder jpql = new StringBuilder();

			jpql.append(" UPDATE Persona p ");
			jpql.append(" SET p.apPaterno = :apPaterno ");
			jpql.append(" ,p.apMaterno = :apMaterno ");
			jpql.append(" ,p.nombres = :nombres ");
			jpql.append(" ,p.fecNacimiento = :fecNacimiento ");
			jpql.append(" ,p.indTipoDocumento = :indtipoDocumento ");
			jpql.append(" ,p.numDocumento = :numDocumento ");
			jpql.append(" ,p.numRuc = :numRuc ");
			jpql.append(" ,p.nomFoto = :nomFoto ");
			jpql.append(" ,p.fecFoto = :fecFoto ");
			jpql.append(" ,p.codTramite = :codTramite ");
			jpql.append(" ,p.estado = :estado ");
			
			jpql.append(" WHERE p.idPersona = :idPersona ");

			Query query = em.createQuery(jpql.toString());

			query.setParameter("idPersona", persona.getIdPersona());
			query.setParameter("apPaterno", persona.getApPaterno());
			query.setParameter("apMaterno", persona.getApMaterno());
			query.setParameter("nombres", persona.getNombres());
			query.setParameter("fecNacimiento", persona.getFecNacimiento());
			query.setParameter("indtipoDocumento",persona.getIndTipoDocumento());
			query.setParameter("numDocumento", persona.getNumDocumento());
			query.setParameter("numRuc", persona.getNumRuc());
			query.setParameter("nomFoto", persona.getNomFoto());
			query.setParameter("fecFoto", persona.getFecFoto());
			query.setParameter("codTramite", persona.getCodTramite());
			query.setParameter("estado", persona.getEstado());
			

			query.executeUpdate();

		} catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_INSERT), e);
		}
		return persona;
	}

	@Override
	public PersonaDTO obtenerPersona(Long idPersona,Long numRuc,String numDocumento) throws Exception {
		PersonaDTO personaDTO = null;
		Persona resultado = null;

		try {
			StringBuilder jpql = new StringBuilder();
			jpql.append(" SELECT pe FROM Persona pe WHERE pe.estado = 1 ");
			
			if(idPersona!=null){jpql.append(" AND pe.idPersona = :idPersona ");}
			if(numRuc!=null){jpql.append(" AND pe.numRuc = :numRuc ");}
			if(numDocumento!=null){jpql.append(" AND pe.numDocumento = :numDocumento ");}
			
			Query query = em.createQuery(jpql.toString());
			
			if(idPersona!=null){query.setParameter("idPersona", idPersona);}
			if(numRuc!=null){query.setParameter("numRuc", numRuc);}
			if(numDocumento!=null){query.setParameter("numDocumento", numDocumento);}
			
			resultado = (Persona) query.getSingleResult();

			personaDTO = PersonaConvert.createDTO(resultado);

		} catch (NoResultException nre) {
			personaDTO = null;
		}catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_GENERAL_DB), e);
		}
		return personaDTO;
	}

	@Override
	public DomicilioDTO obtenerDomicilio(Long idPersona) throws Exception {
		DomicilioDTO domicilioDTO = null;
		Domicilio resultado = null;
		try {
			StringBuilder jpql = new StringBuilder();
			// jpql.append(" SELECT p, a FROM PeriodoAreaOrganica p JOIN  p.areaOrganica a  WHERE 1=1 ");
			jpql.append(" SELECT do FROM Domicilio do WHERE  do.idPersona = :idPersona AND do.estado=1");

			Query query = em.createQuery(jpql.toString());
			query.setParameter("idPersona", idPersona);
			resultado = (Domicilio) query.getSingleResult();

			domicilioDTO = DomicilioConvert.createDTO(resultado);

		} catch (NoResultException nre) {
			domicilioDTO = null;
			 throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_DATA));
		}catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_GENERAL_DB), e);
		}
		return domicilioDTO;
	}

	@Override
	public List<BusquedaFichaDTO> obtenerFichaArbitralAdmin( BusquedaFichaDTO busquedaFicha) throws Exception {

		List<BusquedaFichaDTO> listBusquedaFicha = new ArrayList<BusquedaFichaDTO>();		
		List<FichaArbitral> listArbitralJPA = null;

		try {
			StringBuilder jpql = new StringBuilder();
			jpql.append(" SELECT fa,pe FROM FichaArbitral fa LEFT JOIN fa.persona pe");
			jpql.append(" WHERE pe.idPersona=fa.idPersona");
			if(busquedaFicha.getIdFicha()!=null && busquedaFicha.getIdFicha()!=0)	
				jpql.append(" AND fa.idFicha = :idFicha ");			
			if( busquedaFicha.getApPaterno()!=null && busquedaFicha.getApPaterno().trim().length()>0   )				
				jpql.append(" AND TRIM(pe.apPaterno) LIKE :apPaterno ");
			if( busquedaFicha.getApMaterno()!=null && busquedaFicha.getApMaterno().trim().length()>0   )				
				jpql.append(" AND TRIM(pe.apMaterno) LIKE :apMaterno ");
			if( busquedaFicha.getNombres()!=null && busquedaFicha.getNombres().trim().length()>0 )
				jpql.append(" AND TRIM(pe.nombres) LIKE :nombres ");
			if( busquedaFicha.getNumRuc()!=null && busquedaFicha.getNumRuc()!=0   )
				jpql.append(" AND pe.numRuc = :numRuc");
			if( busquedaFicha.getNumDocumento()!=null && busquedaFicha.getNumDocumento().trim().length()>0 )
				jpql.append(" AND pe.numDocumento = :numDocumento");
			if( busquedaFicha.getNumFicha()!=null && busquedaFicha.getNumFicha().trim().length()>0  )
				jpql.append(" AND TRIM(fa.numFicha) = :numFicha");
		    
			if(busquedaFicha.getFecInicio()!=null && busquedaFicha.getFecFin()==null ){	
					jpql.append(" AND  TO_CHAR(fa.auditoria.fechaRegistro,'dd/mm/yyyy') BETWEEN :fecInicio AND CURRENT_TIMESTAMP");
			}			
			if(busquedaFicha.getFecFin()!=null && busquedaFicha.getFecInicio()!=null){
				jpql.append(" AND  TO_DATE(fa.auditoria.fechaRegistro,'dd/mm/yyyy') BETWEEN :fecInicio AND :fecFin");
			}
			if(busquedaFicha.getTipoFicha()!=null && !isInteger(busquedaFicha.getTipoFicha().trim(), 10))
			{
				jpql.append(" AND fa.tipoFicha = :tipoFicha");	
			
			}
			if( busquedaFicha.getIdEstadoFicha()!=null && busquedaFicha.getIdEstadoFicha()> 0  ){
				jpql.append(" AND fa.idEstadoFicha = :idEstadoFicha");				
			}else{
				jpql.append(" AND fa.idEstadoFicha != 1" );		/**Por defecto traer solo fichas diferentes a estado Pendiente*/		
			}
			
			Query query = em.createQuery(jpql.toString());
			if(busquedaFicha.getIdFicha()!=null && busquedaFicha.getIdFicha()!=0)	
				query.setParameter("idFicha", busquedaFicha.getIdFicha());
			if( busquedaFicha.getApPaterno()!=null && busquedaFicha.getApPaterno().trim().length()>0   )
				query.setParameter("apPaterno", "%"+ busquedaFicha.getApPaterno().trim() + "%");
			if( busquedaFicha.getApMaterno()!=null && busquedaFicha.getApMaterno().trim().length()>0 )		
				query.setParameter("apMaterno", "%"+ busquedaFicha.getApMaterno().trim()+ "%");	
			if( busquedaFicha.getNombres()!=null && busquedaFicha.getNombres().trim().length()>0 )
				query.setParameter("nombres", "%" + busquedaFicha.getNombres().trim() + "%");
			if( busquedaFicha.getNumRuc()!=null && busquedaFicha.getNumRuc()!=0    )
				query.setParameter("numRuc", busquedaFicha.getNumRuc() );
			if( busquedaFicha.getNumDocumento()!=null && busquedaFicha.getNumDocumento().trim().length()>0 )
				query.setParameter("numDocumento", busquedaFicha.getNumDocumento().trim() );
			if( busquedaFicha.getNumFicha()!=null && busquedaFicha.getNumFicha().trim().length()>0 )
				query.setParameter("numFicha", busquedaFicha.getNumFicha().trim() );

			if(busquedaFicha.getFecInicio()!=null && busquedaFicha.getFecFin()==null ){						
						query.setParameter("fecInicio"," TO_CHAR("+busquedaFicha.getFecInicio()+",'dd/mm/yyyy')");
			}
			if(busquedaFicha.getFecFin()!=null && busquedaFicha.getFecInicio()!=null){
					query.setParameter("fecInicio"," TO_CHAR("+busquedaFicha.getFecInicio()+",'dd/mm/yyyy')");
					query.setParameter("fecFin", " TO_CHAR("+ busquedaFicha.getFecFin()+",'dd/mm/yyyy')");
			}
			
			if(busquedaFicha.getTipoFicha()!=null && !isInteger(busquedaFicha.getTipoFicha().trim(), 10))
			{
				
					query.setParameter("tipoFicha", busquedaFicha.getTipoFicha().toString());	
				
			}
			
				
			
			if(  busquedaFicha.getIdEstadoFicha()!=null && busquedaFicha.getIdEstadoFicha()> 0  ){
				query.setParameter("idEstadoFicha", busquedaFicha.getIdEstadoFicha());				
			}
			
			List<Object[]> ListaObjecto= (List<Object[]>)query.getResultList();
			if(!ListaObjecto.isEmpty()) {
				listArbitralJPA=new ArrayList<FichaArbitral>();
				FichaArbitral fichaArbitral = new FichaArbitral();
				for (Object obj [] : ListaObjecto) {
					fichaArbitral=(FichaArbitral)obj[0];
					fichaArbitral.setPersona((Persona)obj[1]);
					listArbitralJPA.add(fichaArbitral);
				}
				listBusquedaFicha=FichaArbitralConvert.createListaBusquedaFichaDTO(listArbitralJPA);
			}		

		} catch (NoResultException nre) {
			 throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_DATA));
		}catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_GENERAL_DB), e);
		}
		return listBusquedaFicha;
	}

	@Override
	public Boolean insertarHistorialPersona(HistorialPersona historialPersona) throws Exception {
		boolean confirmacion=false;
		try {
			em.merge(historialPersona);
			em.flush();
			confirmacion=true;
		} catch (Exception e) {
			confirmacion=false;
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_INSERT), e);
		}
	
		return confirmacion;
	}
	
	@Override
	public Persona consultarPersona(Long idPersona) throws Exception {
		Persona personaJPA = null;
		Persona resultado = null;

		try {
			StringBuilder jpql = new StringBuilder();
			jpql.append(" SELECT pe FROM Persona pe WHERE  pe.idPersona = :idPersona");

			Query query = em.createQuery(jpql.toString());
			query.setParameter("idPersona", idPersona);
			personaJPA = (Persona)query.getSingleResult();
			
		} catch (NoResultException nre) {
			personaJPA = null;
			 throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_DATA));
		}catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_GENERAL_DB), e);
		}
		return personaJPA;
	}
	
	@Override 
	public List<HistorialPersona>  consultarRectificacionesPersona(Long idPersona)
			throws Exception {

				
		List<HistorialPersona> listaHistorialPersonaJPA=null;
		try{
			StringBuilder  	jpql= new StringBuilder();

			jpql.append("SELECT per FROM HistorialPersona per WHERE  per.idPersona = :idPersona ");
						
			Query	query= em.createQuery( jpql.toString() );
			query.setParameter("idPersona", idPersona);			
			List<HistorialPersona>	listaObjeto= query.getResultList();
			if(!listaObjeto.isEmpty()) {
				listaHistorialPersonaJPA=new ArrayList<HistorialPersona>();
				for (HistorialPersona obj: listaObjeto) {					
					listaHistorialPersonaJPA.add(obj);
				}
				
			}		
			
		} catch (NoResultException nre) {
			listaHistorialPersonaJPA = null;
			 throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_NO_DATA));
		}catch (Exception e) {
			throw new ModeloException(propSirenas.getString(ConstanteEJB.EXC_MODELO_GENERAL_DB), e);
		}
		return listaHistorialPersonaJPA;
	}
	
	
	
	
	
	
	
	
	/** base=> base del Numero */
	public static boolean isInteger(String s, int base) {
	    if(s.isEmpty()) return false;
	    for(int i = 0; i < s.length(); i++) {
	        if(i == 0 && s.charAt(i) == '-') {
	            if(s.length() == 1) return false;
	            else continue;
	        }
	        if(Character.digit(s.charAt(i),base) < 0) return false;
	    }
	    return true;
	}
}
